package com.cisco.vsx.email.service.impl;

import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.cisco.vsx.email.Template;
import com.cisco.vsx.email.dao.IEmailTemplateDAO;
import com.cisco.vsx.email.exceptions.EventNotFoundException;
import com.cisco.vsx.email.exceptions.TemplateNotFoundException;
import com.cisco.vsx.email.service.IEmailTemplateService;
import com.mysql.jdbc.StringUtils;

/**
 * @author naresred
 *
 */
@Component
public class EmailTemplateServiceImpl implements IEmailTemplateService {
	
	private static final String TEMPLATE_NAME_NULL_OR_EMPTY = "Template Name can't be Null or Empty";
	private static final String TEMPLATE_BODY_NULL_OR_EMPTY = "Template Body can't be Null or Empty";
	private static final String LOCALE_NAME_NULL_OR_EMPTY = "Locale Name can't be Null or Empty";
	private static final String EVENT_NAME_NULL_OR_EMPTY = "Event Name can't be Null or Empty";
	private static final String TEMPLATE_ID_INVALID = "Template Id is invalid";
	
	@Autowired
	private IEmailTemplateDAO emailTemplateDao;
	
	private static Logger logger = Logger.getLogger(EmailTemplateServiceImpl.class);

	/**
	 * Creates a new email template with specified information. If the event information is not found, this method throws
	 * @EventNotFoundException
	 * 
	 * @param templateName
	 * @param localeName
	 * @param content
	 * @param eventName
	 * @param isDefault
	 * @param isActive
	 * @throws EventNotFoundException
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = { EventNotFoundException.class })
	public void createTemplate(String templateName, String description, String localeName, String content, String eventName, boolean isDefault, boolean isActive) throws EventNotFoundException {
		logger.debug("Entered [createTemplate] of [EmailTemplateServiceImpl]");
		
		if (StringUtils.isNullOrEmpty(templateName)) {
			logger.warn(TEMPLATE_NAME_NULL_OR_EMPTY);
			throw new IllegalArgumentException(TEMPLATE_NAME_NULL_OR_EMPTY);
		}
		
		if (StringUtils.isNullOrEmpty(localeName)) {
			logger.warn(LOCALE_NAME_NULL_OR_EMPTY);
			throw new IllegalArgumentException(LOCALE_NAME_NULL_OR_EMPTY);
		}
		
		if (StringUtils.isNullOrEmpty(content)) {
			logger.warn(TEMPLATE_BODY_NULL_OR_EMPTY);
			throw new IllegalArgumentException(TEMPLATE_BODY_NULL_OR_EMPTY);
		}
		
		if (StringUtils.isNullOrEmpty(eventName)) {
			logger.warn(EVENT_NAME_NULL_OR_EMPTY);
			throw new IllegalArgumentException(EVENT_NAME_NULL_OR_EMPTY);
		}
		
		emailTemplateDao.createTemplate(templateName, description, localeName, content, eventName, isDefault, isActive);
	}	
	
	/**
	 * Updates an email template with the information provided. As there can be multiple templates with the same name 
	 * (template name is NOT unique) template id must be provided. If the template id is not found in the system this
	 * method throws @TemplateNotFoundException  
	 * 
	 * @param templateId
	 * @param templateName
	 * @param description
	 * @param localeName
	 * @param content
	 * @throws TemplateNotFoundException
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = { TemplateNotFoundException.class, EventNotFoundException.class })
	public void updateTemplate(int templateId, String templateName, String description, String localeName, String content, String eventName) throws TemplateNotFoundException, EventNotFoundException {
		logger.debug("Entered [updateTemplate] of [EmailTemplateServiceImpl]");
		
		if (templateId == 0) {
			logger.warn(TEMPLATE_ID_INVALID);
			throw new IllegalArgumentException(TEMPLATE_ID_INVALID);
		}
		
		if (StringUtils.isNullOrEmpty(templateName)) {
			logger.warn(TEMPLATE_NAME_NULL_OR_EMPTY);
			throw new IllegalArgumentException(TEMPLATE_NAME_NULL_OR_EMPTY);
		}
		
		if (StringUtils.isNullOrEmpty(localeName)) {
			logger.warn(LOCALE_NAME_NULL_OR_EMPTY);
			throw new IllegalArgumentException(LOCALE_NAME_NULL_OR_EMPTY);
		}
		
		if (StringUtils.isNullOrEmpty(content)) {
			logger.warn(TEMPLATE_BODY_NULL_OR_EMPTY);
			throw new IllegalArgumentException(TEMPLATE_BODY_NULL_OR_EMPTY);
		}
		
		if (StringUtils.isNullOrEmpty(eventName)) {
			logger.warn(EVENT_NAME_NULL_OR_EMPTY);
			throw new IllegalArgumentException(EVENT_NAME_NULL_OR_EMPTY);
		}
		
		emailTemplateDao.updateTemplate(templateId, templateName, description, localeName, content, eventName);
	}	
	
	/**
	 * Deactivates an email template. Deactivated templates can't be used for sending emails without being activated.
	 * 
	 * @param templateId
	 * @param localeName
	 * @throws TemplateNotFoundException
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = { TemplateNotFoundException.class })
	public void deactivateTemplate(int templateId) throws TemplateNotFoundException {
		logger.debug("Entered [deactivateTemplate] of [EmailTemplateServiceImpl]");
		
		if (templateId == 0) {
			logger.warn(TEMPLATE_ID_INVALID);
			throw new IllegalArgumentException(TEMPLATE_ID_INVALID);
		}
		
		emailTemplateDao.deactivateTemplate(templateId);
	}
	
	/**
	 * Activates a template
	 * 
	 * @param templateId
	 * @throws TemplateNotFoundException
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = { TemplateNotFoundException.class })
	public void activateTemplate(int templateId) throws TemplateNotFoundException {
		logger.debug("Entered [activateTemplate] of [EmailTemplateServiceImpl]");
		
		if (templateId == 0) {
			logger.warn(TEMPLATE_ID_INVALID);
			throw new IllegalArgumentException(TEMPLATE_ID_INVALID);
		}
		
		emailTemplateDao.activateTemplate(templateId);
	}
	
	/**
	 * Deactivates all templates associated to an event
	 * 
	 * @param eventName
	 * @throws EventNotFoundException
	 * @throws TemplateNotFoundException 
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = { TemplateNotFoundException.class, EventNotFoundException.class })
	public void deactivateTemplates(String eventName) throws EventNotFoundException, TemplateNotFoundException {
		logger.debug("Entered [deactivateTemplates] of [EmailTemplateServiceImpl]");
		
		if (StringUtils.isNullOrEmpty(eventName)) {
			logger.warn(EVENT_NAME_NULL_OR_EMPTY);
			throw new IllegalArgumentException(EVENT_NAME_NULL_OR_EMPTY);
		}
		
		emailTemplateDao.deactivateTemplates(eventName);
	}
	
	/**
	 * Activates all templates associated to an event
	 * 
	 * @param eventName
	 * @throws EventNotFoundException
	 * @throws TemplateNotFoundException 
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = { TemplateNotFoundException.class, EventNotFoundException.class })
	public void activateTemplates(String eventName) throws EventNotFoundException, TemplateNotFoundException {
		logger.debug("Entered [activateTemplates] of [EmailTemplateServiceImpl]");
		
		if (StringUtils.isNullOrEmpty(eventName)) {
			logger.warn(EVENT_NAME_NULL_OR_EMPTY);
			throw new IllegalArgumentException(EVENT_NAME_NULL_OR_EMPTY);
		}
		
		emailTemplateDao.activateTemplates(eventName);
	}
		
	/**
	 * Method to get all supported locales for an event
	 * 
	 * @param eventName
	 * @return Set<String>
	 * @throws TemplateNotFoundException
	 */
	@Override
	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS, rollbackFor = { IllegalArgumentException.class, EventNotFoundException.class })
	public Set<String> getSupportedLocales(String eventName) throws EventNotFoundException {
		logger.debug("Entered [getSupportedLocales] of [EmailTemplateServiceImpl]");
		
		if (StringUtils.isNullOrEmpty(eventName)) {
			logger.warn(EVENT_NAME_NULL_OR_EMPTY);
			throw new IllegalArgumentException(EVENT_NAME_NULL_OR_EMPTY);
		}
		
		return emailTemplateDao.getSupportedLocales(eventName);
	}
	
	/**
	 * Retrieves a template with specified Id. If not found, throws @TemplateNotFoundException
	 * 
	 * @param templateId
	 * @return Template
	 * @throws TemplateNotFoundException
	 */
	@Override
	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS, rollbackFor = { IllegalArgumentException.class, TemplateNotFoundException.class })
	public Template getTemplate(int templateId) throws TemplateNotFoundException {
		logger.debug("Entered [getTemplate] of [EmailTemplateServiceImpl]");
		
		if (templateId == 0) {
			logger.warn(TEMPLATE_ID_INVALID);
			throw new IllegalArgumentException(TEMPLATE_ID_INVALID);
		}
		
		return emailTemplateDao.getTemplate(templateId);
	}
	
	/**
	 * Retrieves a template content reader. If not found, throws @TemplateNotFoundException
	 * 
	 * @param templateId
	 * @return Template
	 * @throws TemplateNotFoundException
	 */
	@Override
	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS, rollbackFor = { IllegalArgumentException.class, TemplateNotFoundException.class })
	public Reader getTemplateContentReader(int templateId) throws TemplateNotFoundException {
		logger.debug("Entered [getTemplate] of [EmailTemplateServiceImpl]");
		
		if (templateId == 0) {
			logger.warn(TEMPLATE_ID_INVALID);
			throw new IllegalArgumentException(TEMPLATE_ID_INVALID);
		}
		
		Reader reader = new InputStreamReader(new ByteArrayInputStream(emailTemplateDao.getTemplate(templateId).getContent().getBytes()));
		
		return reader;
	}
		
	/**
	 * Retrieves templates matches the criteria. Returns empty list if no results found.
	 * 
	 * @param eventName
	 * @param localeName
	 * @return List<Template>
	 */
	@Override
	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	public List<Template> getTemplates(Template template) {
		logger.debug("Entered [getTemplates] of [EmailTemplateServiceImpl]");
		
		return emailTemplateDao.getTemplates(template);
	}
	
	/**
	 * Adds an image to template
	 * 
	 * @param templateId
	 * @param imageName
	 * @param content
	 * @param mimeType
	 * @throws TemplateNotFoundException
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = { TemplateNotFoundException.class})
	public void addTemplateContent(int templateId, String imageName, byte[] content, String mimeType, boolean isAttachment) throws TemplateNotFoundException {
		logger.debug("Entered [addImage] of [EmailTemplateServiceImpl]");
		
		emailTemplateDao.addTemplateContent(templateId, imageName, content, mimeType, isAttachment);
	}
	
	/**
	 * Marks an email template as non default.
	 * 
	 * @param templateId
	 * @throws TemplateNotFoundException
	 */
	public void markTemplateAsNonDefault(int templateId) throws TemplateNotFoundException {
		logger.debug("Entered [markTemplateAsNonDefault] of [EmailTemplateServiceImpl]");
		
		emailTemplateDao.markTemplateAsNonDefault(templateId);
	}
	
	/**
	 * Marks an email template as default.
	 * 
	 * @param templateId
	 * @throws TemplateNotFoundException
	 */
	public void markTemplateAsDefault(int templateId) throws TemplateNotFoundException {
		logger.debug("Entered [markTemplateAsDefault] of [EmailTemplateServiceImpl]");
		
		emailTemplateDao.markTemplateAsDefault(templateId);		
	}

}
